<template>
  <div
    class="chart-box"
    style="width: 100%; height: 100%"
    :style="{ backgroundColor: widgetOptions.setup.backgroundColor }"
  >
    <div v-if="!chartStatus" ref="chartRef" style="width: 100%; height: 100%"></div>

    <ChartEmpty v-if="chartStatus" :chartStatus="chartStatus" />
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
import * as echarts from 'echarts'
import { mapper } from '../constants'
import { useTools } from '../../hooks/useTools'
import { useWidgetTools } from '../../hooks/useWidgetTools'
import { useSignalView } from '../../hooks/useSignalView'
import ChartEmpty from '../../components/chartEmpty.vue'

// 接收父组件传入的值
const props = defineProps({
  widgetOptions: {
    type: Object as PropType<Record<string, any>>, // 或更具体的类型
    required: true
  },
  isPreview: {
    type: Boolean,
    default: false
  }
})

const chartRef = ref<HTMLDivElement | null>(null)
let myChart: echarts.ECharts | null = null
const chartData = ref<any>(null)
const { renderErrorBar } = useWidgetTools()

const { toRgba } = useTools()
const mockDataUrl = '/mockdata/realtime/sedStatistics.json'

const initChart = () => {
  if (chartRef.value) {
    // 初始化实例
    myChart = echarts.init(chartRef.value)
  }
}

// 更新配置
const updateOptions = () => {
  if (!chartData.value) return
  const { signalName, startTime, duration, value, extra } = chartData.value
  const signalLabel = mapper[signalName] || ''
  const { avg, median, std, se, mad, percentile5, percentile25, percentile75, percentile95 } = value
  const keys = Object.keys(value)
  const series: any[] = []
  const getBaseSeries = (name, data) => {
    return {
      name: name,
      type: 'bar',
      data: data,
      label: {
        position: 'top',
        formatter: function (params) {
          const { data } = params
          return data[1].toFixed(2)
        }
      },
      smooth: false,
      showSymbol: false,
      itemStyle: {
        color: props.widgetOptions.setup.barColor
      },
      lineStyle: {
        width: props.widgetOptions.setup.lineWidth,
        color: props.widgetOptions.setup.lineColor
      },
      areaStyle: props.widgetOptions.setup.areaStyle
        ? {
            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
              {
                offset: 0,
                color: props.widgetOptions.setup.lineColor
              },
              {
                offset: 1,
                color: toRgba(props.widgetOptions.setup.lineColor, 0.3)
              }
            ])
          }
        : null
    }
  }
  const appendSeries = (name, v1, v2) => {
    series.push(getBaseSeries(name, v1))
    series.push({
      name: name,
      type: 'custom',
      itemStyle: {
        borderWidth: 1.5,
        color: 'red'
      },
      data: v2,
      renderItem: renderErrorBar,
      encode: { tooltip: [1, 2] },
      z: 100
    })
  }
  const avgData = Object.keys(avg).map((p) => [p, avg[p]])
  //均值-标准误
  appendSeries(
    `${mapper['avg'] || 'avg'}_${mapper['se'] || 'se'}`,
    avgData,
    avgData.map((p) => [p[0], p[1] - se[p[0]], p[1] + se[p[0]]])
  )
  //均值-标准差
  appendSeries(
    `${mapper['avg'] || 'avg'}_${mapper['std'] || 'std'}`,
    avgData,
    avgData.map((p) => [p[0], p[1] - std[p[0]], p[1] + std[p[0]]])
  )
  const medianData = Object.keys(median).map((p) => [p, median[p]])
  //中位数-Q1-Q3
  appendSeries(
    `${mapper['median'] || 'median'}_Q1-Q3`,
    medianData,
    medianData.map((p) => [p[0], percentile25[p[0]], percentile75[p[0]]])
  )
  //中位数-5-95
  appendSeries(
    `${mapper['median'] || 'median'}_5th-95th`,
    medianData,
    medianData.map((p) => [p[0], percentile5[p[0]], percentile95[p[0]]])
  )
  //中位数-绝对中位差
  appendSeries(
    `${mapper['median'] || 'median'}_${mapper['mad'] || 'mad'}`,
    medianData,
    medianData.map((p) => [p[0], p[1] - mad[p[0]], p[1] + mad[p[0]]])
  )

  keys.forEach((key) => {
    series.push(
      getBaseSeries(
        mapper[key] || key,
        Object.keys(value[key]).map((p) => [p, value[key][p]])
      )
    )
  })
  const option = {
    title: {
      text: `最近${duration}秒${signalLabel}`,
      subtext: `开始时间：${startTime}`,
      left: 'center',
      textStyle: {
        color: props.widgetOptions.setup.titleColor,
        fontSize: props.widgetOptions.setup.titleFontSize
      },
      subtextStyle: {
        color: props.widgetOptions.setup.subtitleColor,
        fontSize: props.widgetOptions.setup.subtitleFontSize
      }
    },
    tooltip: {
      trigger: 'axis'
    },
    toolbox: {
      itemSize: 25,
      top: 20,
      right: 20,
      feature: {
        magicType: {
          type: ['line', 'bar']
        }
      },
      iconStyle: {
        color: props.widgetOptions.setup.toolboxIconColor,
        borderColor: props.widgetOptions.setup.toolboxIconColor
      }
    },
    legend: {
      type: 'scroll',
      top: '5%',
      left: '10',
      orient: 'vertical',
      selectedMode: 'single',
      itemStyle: {
        color: props.widgetOptions.setup.legendColor
      },
      textStyle: {
        color: props.widgetOptions.setup.legendFontColor,
        fontSize: props.widgetOptions.setup.legendFontSize
      }
    },
    grid: {
      left: '180',
      right: '5%'
    },
    xAxis: {
      type: 'category',
      axisLine: {
        lineStyle: {
          color: props.widgetOptions.setup.xLineColor
        }
      },
      axisLabel: {
        color: props.widgetOptions.setup.xFontColor,
        fontSize: props.widgetOptions.setup.xFontSize
      }
    },
    yAxis: {
      axisLabel: {
        color: props.widgetOptions.setup.yFontColor,
        fontSize: props.widgetOptions.setup.yFontSize
      },
      splitLine: {
        show: props.widgetOptions.setup.ySplitLine,
        lineStyle: {
          color: 'rgba(255,255,255,0.2)'
        }
      }
    },
    series: series
  }

  myChart?.setOption(option)
  myChart?.resize()
}

const resolveData = (data: any) => {
  if (data && data.msgPack) {
    chartStatus.value = ''
    chartData.value = data.msgPack
    updateOptions()
  } else {
    chartStatus.value = 'noData'
    chartData.value = null
  }
}

const resolveMockData = (data: any) => {
  chartData.value = data
  updateOptions()
}

const { chartStatus, refreshData } = useSignalView(
  props.widgetOptions,
  props.isPreview,
  mockDataUrl,
  resolveData,
  resolveMockData
)

onMounted(() => {
  initChart()
  refreshData()
})

// 如果父组件传入的 props.value 改变，需要更新折线图颜色等
watch(
  () => props.widgetOptions,
  () => {
    if (myChart) {
      updateOptions()
    }
  },
  { immediate: true, deep: true }
)

onBeforeUnmount(() => {
  if (myChart) {
    myChart.dispose()
  }
})
</script>

<style scoped></style>
